package org.pblue.tumblarity.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.pblue.tumblarity.data.bean.Tumblelog;
import org.pblue.tumblarity.service.FetchAllService;
import org.pblue.tumblarity.tools.LoginBean;
import org.pblue.tumblarity.tools.TumblrHttpTools;
import org.pblue.tumblarity.view.FollowersView;

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;

/**
 * This is a controller for the form submits from index.jsp, mapped to /controller/editblog. 
 * It has the following parameters:
 * 
 * email (optional): the email address of the Tumblr account,
 * 
 * tumblelog (optional): the name of the tumblelog, if any, (it is only needed if 
 * the registered tumblelog is not the main tumblelog of this Tumblr account),
 * 
 * password (optional): the password of the Tumblr account,
 * 
 * submit (required): the button which was pressed on the form,
 * 
 * successOkUrl (required): the url to redirect to if the OK button was pressed
 * on the form and the processing was successful,
 * 
 * successRemoveUrl (required): the url to redirect to if the Remove button was
 * pressed on the form and the processing was succesful,
 * 
 * errorUrl (required): the url to redirect to if any errors occur.
 * 
 * @author mikolaj
 *
 */
public class EditBlog extends HttpServlet {

  private static final long serialVersionUID = 1L;
  
  public static final String URI_ERROR = "/";
  public static final String URI_REMOVE_OK = "/";
  public static final String ATTR_EMAIL = "email";
  public static final String ATTR_TUMBLELOG_NAME = "tumblelogName";
  public static final String ATTR_MESSAGE = "message";
  public static final String ATTR_ERRORS = "errors";
  
  private static final Logger log = Logger.getLogger(EditBlog.class.getName());
  
  @Override
  protected void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
    HttpSession session = pRequest.getSession();
    
    List<String> errors = new ArrayList<String>();
    String message = "";
    String url = "";
    
    String email = pRequest.getParameter("email");
    String tumblelogName = pRequest.getParameter("tumblelog");
    String password = pRequest.getParameter("password");
    String submit = pRequest.getParameter("submit");
    
    // no email address provided
    if (email == null || email.equals("")) {
      errors.add("Email address is required.");
    }
    
    // no password provided
    if (password == null || password.equals("")) {
      errors.add("Password is required.");
    }
    
    // continue processing if no errors have occured so far
    if (errors.size() == 0) {
      try {
        // check if login was succesful
        LoginBean loginBean = TumblrHttpTools.login(email, password);
        if (!loginBean.isSuccesful()) {
          errors.add("Incorrect email or password.");
          
        // continue processing if login was succesful
        } else {
          
          // check if provided tumblelog name exists in this tumblr account
          if (!TumblrHttpTools.tumblelogExists(email, tumblelogName, password)) {
            errors.add("Tumblelog cannot be found.");
          
          // the tumblelog name exists, so continue processing
          } else {
            
            String authenticationHash = Tumblelog.generateAuthenticationHash(password);
            
            // retrieve tumblelog object from datastore
            Tumblelog tumblelog = Tumblelog.get(email, tumblelogName);
            
            // REMOVE button was clicked, so remove tumblelog from the system
            if (submit.equals("Remove")) {
              if (tumblelog == null) {
                errors.add("Tumblelog not registered.");
              } else {
                tumblelog.remove();
                message = (tumblelogName == null || tumblelogName.equals("") ? email : tumblelogName) + " is not tracked anymore.";
                url = URI_REMOVE_OK;
              }

            // OK button was clicked, so proceed to track page
            } else if (submit.equals("OK")) {
              
              // if a tumblelog object could not have been retrieved from datastore, 
              // then it is a new registration, so create the tumblelog object and save it,
              // and queue a new task to fetch this tumblelog
              if (tumblelog == null) {
                tumblelog = new Tumblelog(email, tumblelogName, password);
                tumblelog.setAuthenticationHash(authenticationHash);
                tumblelog.save();
                
                Queue fetchTumblelogQueue = QueueFactory.getQueue(FetchAllService.QUEUE_FETCH_TUMBLELOG);
                fetchTumblelogQueue.add(TaskOptions.Builder.withUrl("/task/fetchtumblelog").param(FetchAllService.PARAM_TUMBLELOG_ID, tumblelog.getId()));
                
                message = (tumblelogName == null || tumblelogName.equals("") ? email : tumblelogName) + " is being tracked from now.";
              } else {
                tumblelog.setPassword(password);
                tumblelog.setAuthenticationHash(authenticationHash);
                if (tumblelog.getFetchState() == Tumblelog.FETCH_STATE_ERROR) {
                  tumblelog.setFetchState(Tumblelog.FETCH_STATE_IDLE);
                }
                tumblelog.save();
              }

              url = "/" + FollowersView.COMPONENT + "/" + tumblelog.getEmail() + (tumblelog.getTumblelog() == null ? "" : ("/" + tumblelog.getTumblelog()));
            }
            
            pResponse.addCookie(tumblelog.getAuthenticationCookie());
            
          }
        }
      } catch (IOException e) {
        log.log(Level.SEVERE, e.getMessage(), e);
        errors.add("Couldn't connect to Tumblr. Please try again!");
      } catch (Exception e) {
        log.log(Level.SEVERE, e.getMessage(), e);
        errors.add("An error occured. Please try again!");
      }
    }
    
    if (errors.size() > 0) {
      url = URI_ERROR;
    }

    session.setAttribute(ATTR_ERRORS, errors);
    session.setAttribute(ATTR_MESSAGE, message);
    session.setAttribute(ATTR_EMAIL, email);
    session.setAttribute(ATTR_TUMBLELOG_NAME, tumblelogName);
    
    pResponse.sendRedirect(url);     
  }

}
